/********************************************************************
文件名称:   usbd。。。。。.c

文件功能:   usb转can单片机驱动

文件说明:   usb转can单片机驱动 usb转can单片机驱动

当前版本:   V1.0

修改记录:   2016-10-27 16:20:34   王  明  创建
********************************************************************/
#include <stdbool.h>
#include "rl_usb.h"
#include "RTE_Components.h"
#include "Driver_CAN.h"
#include "stdio.h"
#include "string.h"

#define DEBUG 1

// CAN Driver Controller selector
#define  CAN_CONTROLLER         1       // CAN Controller number

#define _CAN_Driver_(n)         Driver_CAN##n
#define  CAN_Driver_(n)        _CAN_Driver_(n)
extern   ARM_DRIVER_CAN         CAN_Driver_(CAN_CONTROLLER);
#define  ptrCAN               (&CAN_Driver_(CAN_CONTROLLER))

uint32_t                        rx_rtr_tx_data_obj_idx = 0xFFFFFFFFU;
uint32_t                        rx_rtr_obj_idx         = 0xFFFFFFFFU;
ARM_CAN_MSG_INFO                rx_rtr_msg_info;
uint32_t                        tx_data_obj_idx        = 0xFFFFFFFFU;
uint8_t                         rx_data[8];
ARM_CAN_MSG_INFO                tx_data_msg_info;

/*------------------------------------------------------------------------------
 *        CAN Signal Unit Event Callback
 *----------------------------------------------------------------------------*/
void CAN_SignalUnitEvent (uint32_t event)
{

    switch (event)
    {
    case ARM_CAN_EVENT_UNIT_ACTIVE:
        break;
    case ARM_CAN_EVENT_UNIT_WARNING:
        break;
    case ARM_CAN_EVENT_UNIT_PASSIVE:
        break;
    case ARM_CAN_EVENT_UNIT_BUS_OFF:
        break;
    }
}

/*------------------------------------------------------------------------------
 *        CAN Signal Object Event Callback
 *----------------------------------------------------------------------------*/
void CAN_SignalObjectEvent (uint32_t obj_idx, uint32_t event)
{
    int size = 0;
    int i = 0;
    
    if (event == ARM_CAN_EVENT_RECEIVE)           // If receive event
    {
        if (obj_idx == rx_rtr_obj_idx)              // If receive object event
        {
            if ((size = ptrCAN->MessageRead(rx_rtr_obj_idx, &rx_rtr_msg_info, rx_data, 8U)) >= 0U)
            {
#if DEBUG
                /* 扩展帧 */
                if((rx_rtr_msg_info.id & 0x80000000) == 0x80000000)
                {
                    printf("Extend frame ID:%#x\n\r", (rx_rtr_msg_info.id & 0x1fffffff));
                }
                else /* 标准帧 */
                {
                    printf("Stander frame ID:%#x \n\r", rx_rtr_msg_info.id);
                }
                printf("rx_rtr_msg_info.rtr %d \n\r", rx_rtr_msg_info.rtr );
                printf("rx_rtr_msg_info.edl %d \n\r", rx_rtr_msg_info.edl );
                printf("rx_rtr_msg_info.brs %d \n\r", rx_rtr_msg_info.brs );
                printf("rx_rtr_msg_info.esi %d \n\r", rx_rtr_msg_info.esi );
                printf("rx_rtr_msg_info.dlc %d \n\r", rx_rtr_msg_info.dlc );
                
                for(i = 0; i < size; i++)
                {
                    printf("%#x ", rx_data[i]);
                }
                printf("\n\r");
                
                memset(&tx_data_msg_info, 0U, sizeof(ARM_CAN_MSG_INFO));                      // Clear data message info structure
                tx_data_msg_info.id = ARM_CAN_EXTENDED_ID(0x11223344U);                       // Set extended ID for transmit data message
                
                ptrCAN->MessageSend(tx_data_obj_idx, &tx_data_msg_info, rx_data, size);
#endif


            }
        }
    }
    if (event == ARM_CAN_EVENT_SEND_COMPLETE)     // If send completed event
    {
#if LOW_LEVL_DEBUG
        printf("ARM_CAN_EVENT_SEND_COMPLETE\n\r");
#endif
    }
}

/*------------------------------------------------------------------------------
 *        Application
 *----------------------------------------------------------------------------*/
int Can1Init(void)
{
    ARM_CAN_CAPABILITIES     can_cap;
    ARM_CAN_OBJ_CAPABILITIES can_obj_cap;
    int32_t                  status;
    uint32_t                 i, num_objects, clock;

    can_cap = ptrCAN->GetCapabilities (); // Get CAN driver capabilities
    num_objects = can_cap.num_objects;    // Number of receive/transmit objects

    status = ptrCAN->Initialize    (CAN_SignalUnitEvent, CAN_SignalObjectEvent);  // Initialize CAN driver
    if (status != ARM_DRIVER_OK )
    {
        return -1;
    }

    status = ptrCAN->PowerControl  (ARM_POWER_FULL);                              // Power-up CAN controller
    if (status != ARM_DRIVER_OK )
    {
       return -2;
    }

    status = ptrCAN->SetMode       (ARM_CAN_MODE_INITIALIZATION);                 // Activate initialization mode
    if (status != ARM_DRIVER_OK )
    {
        return -3;
    }

    clock = ptrCAN->GetClock();                                                   // Get CAN bas clock
    if ((clock % (8U * 125000U)) == 0U)                                           // If CAN base clock is divisible by 8 * 125000 without remainder
    {
        status = ptrCAN->SetBitrate    (ARM_CAN_BITRATE_NOMINAL,                    // Set nominal bitrate
                                        125000U,                                    // Set bitrate to 125 kbit/s
                                        ARM_CAN_BIT_PROP_SEG(5U)   |                // Set propagation segment to 5 time quanta
                                        ARM_CAN_BIT_PHASE_SEG1(1U) |                // Set phase segment 1 to 1 time quantum (sample point at 87.5% of bit time)
                                        ARM_CAN_BIT_PHASE_SEG2(1U) |                // Set phase segment 2 to 1 time quantum (total bit is 8 time quanta long)
                                        ARM_CAN_BIT_SJW(1U));                       // Resynchronization jump width is same as phase segment 2
    }
    else if ((clock % (10U * 125000U)) == 0U)                                     // If CAN base clock is divisible by 10 * 125000 without remainder
    {
        status = ptrCAN->SetBitrate    (ARM_CAN_BITRATE_NOMINAL,                    // Set nominal bitrate
                                        125000U,                                    // Set bitrate to 125 kbit/s
                                        ARM_CAN_BIT_PROP_SEG(7U)   |                // Set propagation segment to 7 time quanta
                                        ARM_CAN_BIT_PHASE_SEG1(1U) |                // Set phase segment 1 to 1 time quantum (sample point at 90% of bit time)
                                        ARM_CAN_BIT_PHASE_SEG2(1U) |                // Set phase segment 2 to 1 time quantum (total bit is 10 time quanta long)
                                        ARM_CAN_BIT_SJW(1U));                       // Resynchronization jump width is same as phase segment 2
    }
    else if ((clock % (12U * 125000U)) == 0U)                                     // If CAN base clock is divisible by 12 * 125000 without remainder
    {
        status = ptrCAN->SetBitrate    (ARM_CAN_BITRATE_NOMINAL,                    // Set nominal bitrate
                                        125000U,                                    // Set bitrate to 125 kbit/s
                                        ARM_CAN_BIT_PROP_SEG(7U)   |                // Set propagation segment to 7 time quanta
                                        ARM_CAN_BIT_PHASE_SEG1(2U) |                // Set phase segment 1 to 2 time quantum (sample point at 83.3% of bit time)
                                        ARM_CAN_BIT_PHASE_SEG2(2U) |                // Set phase segment 2 to 2 time quantum (total bit is 12 time quanta long)
                                        ARM_CAN_BIT_SJW(2U));                       // Resynchronization jump width is same as phase segment 2
    }
    else
    {
        return -4;
    }
    if (status != ARM_DRIVER_OK )
    {
        return -5;
    }

    for (i = 0U; i < num_objects; i++)                                            // Find first available object for receive and transmit
    {
        can_obj_cap = ptrCAN->ObjectGetCapabilities (i);                            // Get object capabilities

#if LOW_LEVL_DEBUG
        printf("**********************num_objects=%d***********************\n\r",i);
        printf("can_obj_cap.multiple_filters = %d\n\r", can_obj_cap.multiple_filters);
        printf("can_obj_cap.exact_filtering = %d\n\r", can_obj_cap.exact_filtering);
        printf("can_obj_cap.range_filtering = %d\n\r", can_obj_cap.range_filtering);
        printf("can_obj_cap.mask_filtering = %d\n\r", can_obj_cap.mask_filtering);
        printf("************************************************************\n\r");
#endif

        if      ((rx_rtr_tx_data_obj_idx == 0xFFFFFFFFU) && (can_obj_cap.rx_rtr_tx_data == 1U))
        {
            rx_rtr_tx_data_obj_idx = i;
            break;
        }
        else if ((rx_rtr_obj_idx         == 0xFFFFFFFFU) && (can_obj_cap.rx             == 1U))
        {
            rx_rtr_obj_idx         = i;
        }
        else if ((tx_data_obj_idx        == 0xFFFFFFFFU) && (can_obj_cap.tx             == 1U))
        {
            tx_data_obj_idx        = i;
            break;
        }
    }
    if ((rx_rtr_tx_data_obj_idx == 0xFFFFFFFFU) && ((rx_rtr_obj_idx == 0xFFFFFFFFU) || (tx_data_obj_idx == 0xFFFFFFFFU)))
    {
        return -6;
    }

    if (rx_rtr_tx_data_obj_idx != 0xFFFFFFFFU)                                    // If rx RTR tx data object is available
    {
        status = ptrCAN->ObjectSetFilter(rx_rtr_tx_data_obj_idx,ARM_CAN_FILTER_ID_MASKABLE_ADD,ARM_CAN_EXTENDED_ID(0x11223344), 0x0);
        if (status != ARM_DRIVER_OK )
        {
            return -7;
        }
        
        status = ptrCAN->ObjectSetFilter(rx_rtr_tx_data_obj_idx,ARM_CAN_FILTER_ID_MASKABLE_ADD,ARM_CAN_STANDARD_ID(0x11223344), 0x0);
        if (status != ARM_DRIVER_OK )
        {
            return -7;
        }


        // Configure rx RTR tx data object
        status = ptrCAN->ObjectConfigure(rx_rtr_tx_data_obj_idx, ARM_CAN_OBJ_RX_RTR_TX_DATA);
        if (status != ARM_DRIVER_OK )
        {
            return -8;
        }
    }
    else
    {
        // /* Set filter to receive messages with extended ID 0x11223344 */
        status = ptrCAN->ObjectSetFilter(rx_rtr_obj_idx,ARM_CAN_FILTER_ID_MASKABLE_ADD,ARM_CAN_EXTENDED_ID(0x11223344), 0x0);
        if (status != ARM_DRIVER_OK )
        {
            return -9;
        }
        
        // /* Set filter to receive messages with extended ID 0x11223344 */
        status = ptrCAN->ObjectSetFilter(rx_rtr_obj_idx,ARM_CAN_FILTER_ID_MASKABLE_ADD,ARM_CAN_STANDARD_ID(0x11223344), 0x0);
        if (status != ARM_DRIVER_OK )
        {
            return -9;
        }

        status = ptrCAN->ObjectConfigure(tx_data_obj_idx, ARM_CAN_OBJ_TX);          // Configure standard transmit object
        if (status != ARM_DRIVER_OK )
        {
            return -10;
        }

        status = ptrCAN->ObjectConfigure(rx_rtr_obj_idx,  ARM_CAN_OBJ_RX);          // Configure standard receive object
        if (status != ARM_DRIVER_OK )
        {
            return -11;
        }
    }

    status = ptrCAN->SetMode (ARM_CAN_MODE_NORMAL);                               // Activate normal operation mode
    if (status != ARM_DRIVER_OK )
    {
        return -12;
    }
    
    return 0;
}

/* USB发送完成回调函数，单片机usb协议栈回调 */
void USBD_CDCn_ACM_DataSent (void)
{

}

/* USB接收完成回调 ，单片机usb协议栈回调 */
void USBD_CDC0_ACM_DataReceived (uint32_t len)
{

}

/* USB CDC初始化回调函数，单片机usb协议栈回调 */
void USBD_CDC0_ACM_Initialize (void)
{
    int ret = 0;

#if LOW_LEVL_DEBUG
    printf("USBD_CDC0_ACM_Initialize was call!\n\r");
#endif
    ret = Can1Init();
    if(ret < 0)
    {
        printf("Can1Init faild!\n\r");
    }
    else
    {
#if LOW_LEVL_DEBUG
        printf("Can1Init succeed!\n\r");
#endif
    }
}

/* USB CDC资源释放回调函数，单片机usb协议栈回调 */
void USBD_CDC0_ACM_Uninitialize (void)
{

}

/* USB CDC复位回调函数，单片机usb协议栈回调 */
void USBD_CDC0_ACM_Reset (void)
{

}

/* USB CDC SetLineCoding 回调函数，单片机usb协议栈回调 */
bool USBD_CDC0_ACM_SetLineCoding (CDC_LINE_CODING *line_coding)
{
    return true;
}

/* USB CDC GetLineCoding 回调函数，单片机usb协议栈回调 */
bool USBD_CDC0_ACM_GetLineCoding (CDC_LINE_CODING *line_coding)
{
    return true;
}

/* USB CDC SetControlLineState 回调函数，单片机usb协议栈回调 */
bool USBD_CDC0_ACM_SetControlLineState (uint16_t state)
{
    return true;
}
